package remote

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

type httpGetter struct {
	baseURL string // eg  127.0.0.1:5252/_cache/
}

// The remote call gets the value
func (h *httpGetter) Get(cacheName string, key string) ([]byte, error) {
	// Path joining together /_cache/(cacheName)/(_get)/(key)
	u := fmt.Sprintf("http://%v/%v/_get/%v", h.baseURL, url.QueryEscape(cacheName), url.QueryEscape(key))

	res, err := http.Get(u)

	if err != nil {
		return nil, err
	}

	defer res.Body.Close()

	// The response code is not 200
	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("server return code: %d", res.StatusCode)
	}

	// Read all bytes
	bytes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, fmt.Errorf("reading response body: %v", err)
	}
	result := make(map[string]string)
	_ = json.Unmarshal(bytes, &result)
	return []byte(result["data"]), nil
}

// The remote call deletes the value
func (h *httpGetter) Delete(cacheName string, key string) error {
	// Path joining together /_cache/(cacheName)/_del/(keys)
	u := fmt.Sprintf("http://%v/%v/_del/%v", h.baseURL, url.QueryEscape(cacheName), url.QueryEscape(key))

	res, err := http.Get(u)

	if err != nil {
		return err
	}

	defer res.Body.Close()

	//The response code is not 200
	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("reading response body: %v", err)
	}

	return nil
}

func (h *httpGetter) Set(cacheName string, key string, value string, ttl ...int64) error {
	var u string
	if len(ttl) == 1 {
		// Path joining together /_cache/(cacheName)/_set/(keys)/(value)/(ttl)
		u = fmt.Sprintf("http://%v/%v/_set/%v/%v/%v", h.baseURL, url.QueryEscape(cacheName), url.QueryEscape(key), url.QueryEscape(value), url.QueryEscape(strconv.FormatInt(ttl[0], 10)))
	} else {
		// Path joining together /_cache/(cacheName)/_set/(keys)/(value)
		u = fmt.Sprintf("http://%v/%v/_set/%v/%v", h.baseURL, url.QueryEscape(cacheName), url.QueryEscape(key), url.QueryEscape(value))
	}

	res, err := http.Get(u)

	if err != nil {
		return err
	}

	defer res.Body.Close()

	//The response code is not 200
	if res.StatusCode != http.StatusOK {
		return fmt.Errorf("reading response body: %v", err)
	}

	return nil
}
